<?php

namespace App\Log\Service;

use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Str;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Config;

class LogViewerService
{
    protected $config;
    protected $logName;

    /**
     * 扩展包名
     */
    const PACKAGE_NAME = 'logviewer';

    /**
     * 日志等级
     */
    const LOG_LEVEL_INFO      = 'info';
    const LOG_LEVEL_ERROR     = 'error';
    const LOG_LEVEL_NOTICE    = 'notice';
    const LOG_LEVEL_WARNING   = 'warning';
    const LOG_LEVEL_DEBUG     = 'debug';
    const LOG_LEVEL_ALERT     = 'alert';
    const LOG_LEVEL_EMERGENCY = 'emergency';
    const LOG_LEVEL_CRITICAL  = 'critical';

    public function __construct()
    {
        $this->config = config(self::PACKAGE_NAME);
       /// $this->config = config('request');

        //dd($this->config);
        App::setLocale($this->config['locale_language']);

    }

    /**
     * 获取包名
     * @return string
     */
    public function getPackageName()
    {
        return self::PACKAGE_NAME;
    }

    /**
     * 获取所有日志
     * @param string $keywords 关键字
     * @return array
     */
    public function getAllLogs($keywords = null)
    {
        $logs = [];
        foreach (File::allFiles(storage_path('logs')) as $log) {
            $pathName = $log->getRelativePathname();

            if (Str::contains($pathName, $keywords)) {
                $logs[] = $log->getRelativePathname();
            }

            if (!$keywords) {
                $logs[] = $log->getRelativePathname();
            }
        }
        //dd($logs);
        return array_reverse($logs);
    }

    /**
     * 设置日志路径
     * @param $logName
     */
    public function setLogPath($logName)
    {
        //dd($logName);
        $this->logName = $logName;
    }

    /**
     * 获取日志名
     * @return string
     */
    public function getLogName()
    {
        return $this->logName;
    }

    /**
     * 获取日志路径
     * @return string
     */
    public function getLogPath()
    {
        return storage_path('logs' . DIRECTORY_SEPARATOR . $this->logName);
    }

    /**
     * 获取日志大小
     * @return string
     */
    public function getLogSize()
    {
        $bytes = File::size($this->getLogPath());

        $size = ['B', 'K', 'M', 'G', 'T'];
        for ($i = 0; $bytes >= 1024 && $i < 4; $i++) {
            $bytes /= 1024;
        }
        return round($bytes, 2) . ' ' . $size[$i];
    }

    /**
     * 获取日志最后修改时间
     * @return string
     */
    public function getLogModified()
    {
        return Carbon::parse(File::lastModified($this->getLogPath()))->format('Y-m-d H:i:s');
    }
    //获取日志打印内容
    public function ddgetLogContents()
    {
        $data=$_REQUEST;
        $is_y=0;
        if(isset($data['is_y'])){
            $is_y=$data['is_y'];
        }
        $content = File::sharedGet($this->getLogPath());
        if($is_y!=1){
            //判断是否包含某个字符
            if (str_contains($this->getLogPath(),'request')) {
                $content=$this->ddgetLogContents1();
                //dd($content);

            }

            if (str_contains($this->getLogPath(),'query')) {
                $content=$this->ddgetLogContents2();
            }
        }
        //$content=array_reverse($content);
        dd($content);

    }
   
    public function ddgetLogContents1(){
        $content = File::sharedGet($this->getLogPath());
        //dd($content);
        $parts = explode(" \n", $content);
        $new_ar=[];
        foreach($parts as $k=>$v){
            if($k % 2 == 0){
                $format = 'Y-m-d H:i:s';
                // 解析字符串
                $parsedDate = date_parse_from_format($format,$v);
                $time = sprintf('%02d:%02d:%02d', $parsedDate['hour'], $parsedDate['minute'], $parsedDate['second']);

                $time=$parsedDate['year'].'-'.$parsedDate['month'].'-'.$parsedDate['day'].' '.$time;
                //dd($time);
            }else{
                $n=$k-1;
                $format = 'Y-m-d H:i:s';
                // 解析字符串
                $parsedDate = date_parse_from_format($format,$parts[$n]);
                $time = sprintf('%02d:%02d:%02d', $parsedDate['hour'], $parsedDate['minute'], $parsedDate['second']);

                $time=$parsedDate['year'].'-'.$parsedDate['month'].'-'.$parsedDate['day'].' '.$time;
                //dd($time);
                $v_ar=explode("\n",$v);
                //去除多余字段
                unset($v_ar['9']);
                unset($v_ar['10']);
                unset($v_ar['11']);
                
               // dd($v_ar);
                $tt=implode("\n",$v_ar);
                //$tt =preg_replace('/\n/', '', $tt);
                //dd($tt);
                $new_ar[$time]=$tt;
               
            }

        }
        $new_ar=array_reverse($new_ar);
       // $new_ar=implode("\n",$new_ar);
        return $new_ar;
    }
    public function ddgetLogContents2(){
        $content = File::sharedGet($this->getLogPath());
        $parts = explode("\r\n", $content);
        $parts = array_reverse($parts);
        $parts = array_filter($parts);
        $parts = implode("\n",$parts);
        return $parts;
    }
    //query
    public function getLogContents2()
    {
        $content = File::sharedGet($this->getLogPath());
        $parts = explode("\r\n", $content);
        $parts = array_reverse($parts);
        $parts = array_filter($parts);
        //dd($parts);
        $logs = [];
        foreach ($parts as $k=>$match) {
            $format = 'Y-m-d H:i:s';
            // 解析字符串
            $parsedDate = date_parse_from_format($format,$match);
            $time = sprintf('%02d:%02d:%02d', $parsedDate['hour'], $parsedDate['minute'], $parsedDate['second']);

            $time=$parsedDate['year'].'-'.$parsedDate['month'].'-'.$parsedDate['day'].' '.$time;
            //dd($time);
            $logs[] =[
                    'datetime' => $time,
                    'env'      => '本地',
                    'level'    => 'info',
                    'message'  => trim($match),
            ];
        }
        //dd($logs);
        return $logs;
        
    }
    //request
    public function getLogContents1()
    {
        $content = File::sharedGet($this->getLogPath());
        //dd($content);
        $parts = explode(" \n", $content);
        $new_ar=[];
        foreach($parts as $k=>$v){
            if($k % 2 == 0){
                $format = 'Y-m-d H:i:s';
                // 解析字符串
                $parsedDate = date_parse_from_format($format,$v);
                $time = sprintf('%02d:%02d:%02d', $parsedDate['hour'], $parsedDate['minute'], $parsedDate['second']);

                $time=$parsedDate['year'].'-'.$parsedDate['month'].'-'.$parsedDate['day'].' '.$time;
                //dd($time);
            }else{
                $n=$k-1;
                $format = 'Y-m-d H:i:s';
                // 解析字符串
                $parsedDate = date_parse_from_format($format,$parts[$n]);
                $time = sprintf('%02d:%02d:%02d', $parsedDate['hour'], $parsedDate['minute'], $parsedDate['second']);

                $time=$parsedDate['year'].'-'.$parsedDate['month'].'-'.$parsedDate['day'].' '.$time;
                //dd($time);
                $v_ar=explode("\n",$v);
                //去除多余字段
                unset($v_ar['9']);
                unset($v_ar['10']);
                unset($v_ar['11']);
                //$v_ar['11']='时间 : '.$time;
                $tt=implode("\n",$v_ar);
                //$tt =preg_replace('/\n/', '', $tt);
                //dd($tt);
                $new_ar[$time]=$tt;
               
            }

        }
        $new_ar=array_reverse($new_ar);
        $logs = [];
        foreach ($new_ar as $k=>$match) {
           
            //dd($time);
            $logs[] =[
                    'datetime' => $k,
                    'env'      => '本地',
                    'level'    => 'info',
                    'message'  => trim($match),
            ];
        }
        //dd($logs);
        return $logs;

    }
    //编码-将HTML转为实体
    /**
     * 将HTML转为实体
     * @param string $str     需要处理的字符串
     * @param string $charset 编码，默认为gb2312
     * @return string
     */
    public function html_to_entities($str, $charset = "gb2312")
    {
       // 参数判断
        if(empty($str)) return "";
        
        // 1.将常用的预定义字符转为实体
        $new_str = htmlspecialchars($str, ENT_QUOTES, $charset);

        // 2.替换反斜杠
        $new_str = preg_replace("/\\\/", "&#092;", $new_str);

        // 3.替换斜杠
        $new_str = preg_replace("/\//", "&#47;", $new_str);
        
        return $new_str;
    }
    //解码-将实体转为HTML
    /**
     * 将实体转为HTML
     * @param string $str     需要处理的字符串
     * @return string
     */
    public function entities_to_html($str)
    {
       // 参数判断
        if(empty($str)) return "";
        
        // 1.将实体转为预定义字符
        $new_str = htmlspecialchars_decode($str, ENT_QUOTES);

        // 2.替换反斜杠实体
        $new_str = str_replace("&#092;", "\\", $new_str);

        // 3.替换斜杠实体
        $new_str = str_replace("&#47;", "/", $new_str);
        
        return $new_str;
    }


    /**
     * 获取日志内容
     * @return array
     */
    public function getLogContents()
    {
        //获取文件名
        $filename=str_replace('request-','',$this->logName);

        $content1=[];
        //判断是否包含某个字符
        if (str_contains($this->getLogPath(),'request')) {
            $content1=$this->getLogContents1();
            return $content1;
            //dd($content1);
           // $this->logName='laravel-'.$filename;
        }

        if (str_contains($this->getLogPath(),'query')) {
            $content2=$this->getLogContents2();
            return $content2;
           // $this->logName='laravel-'.$filename;
        }

        if (file_exists($this->getLogPath())) {
            //die("sfsd");
            $content = File::sharedGet($this->getLogPath());
            //dd($content);
            $pattern = "/^\[(?<datetime>.*)\]\s(?<env>\w+)\.(?<level>\w+):(?<message>.*)/m";

            preg_match_all($pattern, $content, $matches, PREG_SET_ORDER, 0);
           // dd($matches);
            $logs = [];
            foreach ($matches as $k=>$match) {
                $logs[] = [
                    'datetime' => $match['datetime'],
                    'env'      => $match['env'],
                    'level'    => strtolower($match['level']),
                    'message'  => trim($match['message']),
                   
                ];
            }
            $logs=array_reverse($logs);
            //dd($logs);
            return $logs;
        }
     
    }

    /**
     * 获取日志等级图标
     * @param $level
     * @return mixed
     */
    public function getLevelIcon($level)
    {
        $icons = [
            self::LOG_LEVEL_INFO      => 'fa-info-circle',
            self::LOG_LEVEL_ERROR     => 'fa-times-circle',
            self::LOG_LEVEL_NOTICE    => 'fa-question-circle',
            self::LOG_LEVEL_WARNING   => 'fa-warning',
            self::LOG_LEVEL_DEBUG     => 'fa-question-circle',
            self::LOG_LEVEL_ALERT     => 'fa-info-circle',
            self::LOG_LEVEL_CRITICAL  => 'fa-times-circle',
            self::LOG_LEVEL_EMERGENCY => 'fa-warning',
        ];

        return $icons[strtolower($level)];
    }

    /**
     * 获取日志等级颜色
     * @param $level
     * @return mixed
     */
    public function getLevelColor($level)
    {
        $icons = [
            self::LOG_LEVEL_INFO      => 'text-success',
            self::LOG_LEVEL_ERROR     => 'text-danger',
            self::LOG_LEVEL_NOTICE    => 'text-warning',
            self::LOG_LEVEL_WARNING   => 'text-warning',
            self::LOG_LEVEL_DEBUG     => 'text-debug',
            self::LOG_LEVEL_ALERT     => 'text-warning',
            self::LOG_LEVEL_CRITICAL  => 'text-danger',
            self::LOG_LEVEL_EMERGENCY => 'text-warning',
        ];

        return $icons[strtolower($level)];
    }

    /**
     * 授权检测
     * @return bool
     */
    public function authorization()
    {
        return  true;
        return app()->environment('local') || Gate::allows($this->getPackageName());
    }

}
